'''
File: \adjuge.py
Project: TRANS
Created Date: Sunday December 8th 2019
Author: Huisama
-----
Modified By: the developer formerly known as Huisama at <yuwenhuisama@outlook.com>
-----
Copyright (c) 2019 Huisama
'''
import cv2
import math
import numpy as np

def _img_preprocess(img_input, gaussian_kernel, binary_threshold):
    org_img = cv2.imread(img_input)
    gray_img = cv2.cvtColor(org_img, cv2.COLOR_BGR2GRAY)
    # 高斯模糊去噪（设定卷积核大小影响效果）
    blurred = cv2.GaussianBlur(gray_img, gaussian_kernel, 0)
    _, red_thresh = cv2.threshold(blurred, binary_threshold, 255, cv2.THRESH_BINARY) 
    # 定义矩形结构元素
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    # 闭运算（链接块）
    closed = cv2.morphologyEx(red_thresh, cv2.MORPH_CLOSE, kernel)
    # 开运算（去噪点）
    opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, kernel)
    return org_img, gray_img, red_thresh, closed, opened


def _getContours(org_img, opened):
    _, contours, _ = cv2.findContours(opened, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    # 计算最大轮廓的旋转包围盒
    c = sorted(contours, key=cv2.contourArea, reverse=True)[1]
    # 获取包围盒（中心点，宽高，旋转角度）
    rect = cv2.minAreaRect(c)                           
    box = np.int0(cv2.boxPoints(rect))
    draw_img = cv2.drawContours(org_img.copy(), [box], -1, (0, 0, 255), 3)

    # print("box[0]:", box[0])
    # print("box[1]:", box[1])
    # print("box[2]:", box[2])
    # print("box[3]:", box[3])
    return box, draw_img

def _perspective_transform(box, org_img):
    # 获取画框宽高(x=orignal_W,y=orignal_H)
    orignal_w = math.ceil(np.sqrt((box[3][1] - box[2][1])**2 + (box[3][0] - box[2][0])**2))
    orignal_h= math.ceil(np.sqrt((box[3][1] - box[0][1])**2 + (box[3][0] - box[0][0])**2))

    # 角点，变换矩阵
    pts1 = np.float32([box[0], box[1], box[2], box[3]])
    pts2 = np.float32([[int(orignal_w + 1),int(orignal_h + 1)], [0, int(orignal_h + 1)], [0, 0], [int(orignal_w + 1), 0]])

    # 透视变换
    M = cv2.getPerspectiveTransform(pts1, pts2)
    result_img = cv2.warpPerspective(org_img, M, (int(orignal_w + 3),int(orignal_h + 1)))

    return result_img

def get_contours(img_path, gaussian_kernel=(9, 9), binary_threshold=250):
    """ 获取图像角点

    Args：
        img_path: 图像文件路径
        gaussian_kernel: 高斯模糊时使用的卷积核的大小，调整该参数会影响结果，默认为 (9,9)
        binary_thereshold：图像通过灰度图进行二值化的阈值，调整该参数会影响结果，默认为 250

    Returns：
        list，包含4个角点
    """
    org_img, _, _, _, opened = _img_preprocess(img_path, gaussian_kernel, binary_threshold)
    box, _ = _getContours(org_img, opened)
    return box

def get_adjusted_img(img_path, gaussian_kernel=(9, 9), binary_threshold=250):
    """ 获取矫正后的图像

    Args：
        img_path: 图像文件路径
        gaussian_kernel: 高斯模糊时使用的卷积核的大小，调整该参数会影响结果，默认为 (9,9)
        binary_thereshold：图像通过灰度图进行二值化的阈值，调整该参数会影响结果，默认为 250

    Returns：
        OpenCV的image对象
    """
    org_img, _, _, _, opened = _img_preprocess(img_path, gaussian_kernel, binary_threshold)
    box, _ = _getContours(org_img, opened)
    result_img = _perspective_transform(box, org_img)
    return org_img, result_img

